import axios from 'axios'
import router from '@/router'
import { isCanceled } from '@/utils'
import Message from '@/plugins/message-box'
import lstore from '@/plugins/lstore/lstore.js'
import { plusMessageFirst } from '@/filters'

let cancel
let pending = {}
/**
 * api base url
 */
export const baseURL =
  process.env.NODE_ENV === 'production'
    ? `${process.env.VUE_APP_API_HOST}/api/${process.env.VUE_APP_API_VERSION}`
    : '/api/v2'

const instance = axios.create({
  baseURL,
  headers: {
    'X-Requested-With': 'XMLHttpRequest'
  },
  withCredentials: true,
  crossDomain: true
})

// 请求拦截器
instance.interceptors.request.use(
  config => {
    // 开发环境静态资源重定向
    if (process.env.NODE_ENV === 'development') {
      config.url = config.url.replace(
        /^http:\/\/dev-mn-server\.zhibocloud\.cn\/storage/,
        'http://localhost:8080/storage'
      )
    }
    // 发起请求时，取消掉当前正在进行的相同请求
    if (pending[config.url]) {
      pending[config.url]('Operation cancelled')
      pending[config.url] = cancel
    } else {
      pending[config.url] = cancel
    }
    const TOKEN = lstore.getData('H5_ACCESS_TOKEN')
    if (TOKEN) {
      config.headers.token = TOKEN
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器即异常处理
instance.interceptors.response.use(
  res => res,
  err => {
    const requireAuth = () => {
      setTimeout(() => {
        router.push({
          path: '/signin',
          query: { redirect: router.currentRoute.fullPath }
        })
      }, 500)
    }
    if (!axios.isCancel(err)) {
      if (err && err.response) {
        switch (err.response.status) {
          case 400:
            err.tips = 'Bad request'
            break
          case 401:
            err.tips = lstore.hasData('H5_CUR_USER') ? 'Login failed, please log in again' : 'please log in first'
            lstore.clearData()
            requireAuth()
            break
          case 403:
            err.tips = plusMessageFirst(err.response.data, 'Access Denied') || 'Server error'
            break
          case 404:
            err.tips = 'Request error, the resource was not found'
            break
          case 405:
            err.tips = 'Request method not allowed'
            break
          case 408:
            err.tips = 'Request timed out'
            break
          case 422: {
            const { data } = err.response
            err.tips = plusMessageFirst(data, 'Error request')
            break
          }
          case 500:
            err.tips = 'Network error, please contact the administrator'
            break
          case 501:
            err.tips = 'Network not implemented'
            break
          case 502:
            err.tips = 'Bad Gateway'
            break
          case 503:
            err.tips = 'Service Unavailable'
            break
          case 504:
            err.tips = 'Gateway Timeout'
            break
          case 505:
            err.tips = 'HTTP Version Not Supported'
            break
          default:
            err.tips = 'Error ' + err.response.status
        }
      } else {
        err.tips = 'Lost connection with the server!'
      }
      Message.error(err.tips)
    }
    return Promise.reject(err)
  }
)

/**
 * 标准化API错误.
 *
 * @param {*} error
 * @return {Object}
 */
export const normError = error => {
  let status, message, errors
  const canceled = isCanceled(error) || axios.isCancel(error)

  if (!canceled && error && error.response) {
    status = error.response.status
    const data = error.response.data

    if (typeof data === 'object') {
      errors = { ...(data.errors || data) }

      if (!data.errors) {
        const keys = ['message', 'line', 'file', 'trace', 'exception']
        keys.forEach(key => {
          if (key in errors) {
            delete errors[key]
          }
        })
      }

      if (Object.keys(errors).length) {
        for (const key in errors) {
          message = errors[key]
          break
        }
      } else {
        message = data.message
      }

      if (Array.isArray(message)) {
        message = message.join('\n')
      }
    } else {
      message = `${data}`
    }
  } else {
    message = (error && error.message) || `${error || ''}`
  }

  return { status, message, errors, canceled }
}

export default instance
